#pragma once
#include <memory>
#include <string>
#include <unordered_map>
#include "InnerType.h"
#include "XnccClient.h"
#include "XnccType.h"

namespace xncc {
namespace foundation {
    class EventLoop;
    class XnccAddress;
    class DatagramSocketChannel;

    class DatagramClient final : public XnccClient
    {
      public:
        DatagramClient(EventLoop* loop, std::shared_ptr<XnccAddress> serverAddr);
        ~DatagramClient() override;

        DatagramClient(const DatagramClient&)             = delete;
        DatagramClient(const DatagramClient&&)            = delete;
        DatagramClient& operator=(const DatagramClient&)  = delete;
        DatagramClient& operator=(const DatagramClient&&) = delete;

        void init() override;
        void connect() override;
        auto Type() const -> shared::XNCC_CLIENT_TYPE override { return shared::XNCC_CLIENT_TYPE::DGRAM; }
        void disconnect();
        void stop();
        bool retry() const { return retry_; }

      private:
        void newConnection(int sockfd);
        void removeConnection(types::connection_id_t connId, const std::string& disconnectedReason);

        void handleIoMsg(const char* msg, uint32_t len, types::thread_id_t tid, types::connection_id_t connId);

        EventLoop*                                      loop_;
        bool                                            connect_;  // atomic
        std::shared_ptr<DatagramSocketChannel>          serverChannel_;
        int                                             nextConnId_;
        std::shared_ptr<XnccAddress>                    serverAddr_;
        std::string                                     serverAddrStr_;
        std::unordered_map<types::connection_id_t, int> connIdFd_;
    };
}  // namespace foundation
}  // namespace xncc